/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#ifndef MK_MEDIA_SOURCE_H
#define MK_MEDIA_SOURCE_H
#include "MkMedia/MkMediaUtil.h"
#include "MkUtil/MkRwLock.h"
#include <atomic>

class CMkAudioParam;
class CMkVideoParam;
class CMkMediaSource;
class CMkMediaConsume;
class CMkMediaConsumer;


typedef MkFunction<Uint32(const MkEsPacket& EsPacket, const CMkVideoParam& VideoParam, const CMkAudioParam& AudioParam)>                   MkEsPacketCallback;
typedef MkFunction<Uint32(CMkMediaSource* pSource)>                                                                                        MkSourceAddCallback;
typedef MkFunction<Uint32(const MkString& SourceSession)>                                                                                  MkSourceDeleteCallback;
typedef MkFunction<Uint32(const MkString& SourceSession, CMkMediaConsume* pConsume, CMkMediaConsumer* pConsumer)>                          MkConsumerAddCallback;
typedef MkFunction<Uint32(const MkString& SourceSession, const MkMediaConsumeType& ConsumeType, const MkString& ConsumerSession)>          MkConsumerClosedCallback;
typedef MkFunction<Uint32(CMkMediaSource* pSource, Uint32 ErrorCode)>                                                                      MkSourceResultCallback;
typedef MkFunction<Uint32(const MkString& Path, CMkVideoParam& VideoParam, CMkAudioParam& AudioParam, Uint32& Duration, Uint32& FileSize, MkString& SourceSession)> MkGetSourceParamCallback;
typedef MkFunction<Uint32(CMkMediaConsumer* pConsumer, const MkPlaybackControlType& ControlType, float fSpeed, Uint32 offsetSec)>          MkConsumerPlayCtrlCallback;
typedef struct _media_call_backs
{
    MkSourceAddCallback           SourceAddCb;
    MkSourceDeleteCallback        SourceDeleteCb;
    MkGetSourceParamCallback      GetSourceParamCb;
    MkConsumerAddCallback         ConsumerAddCb;
    MkConsumerClosedCallback      ConsumerClosedCb;
    MkConsumerPlayCtrlCallback    ConsumerPlayCtrlCb;
}MkMediaCallbacks;
class MkApi CMkMediaSource
{
public:
    CMkMediaSource(const MkMediaSourceType& SourceType);
    virtual ~CMkMediaSource();

    static void SetCachePacket(BOOL bCache) { m_bCachePacket = bCache; }
    virtual Uint32 StartMediaSource(const MkSourceResultCallback& ResultCb, const MkEsPacketCallback& EsCb = nullptr);
    virtual Uint32 StopMediaSource();
    virtual Uint32 PlayControl(const MkPlaybackControlType& ControlType, float fSpeed, Uint32 offsetSec);
    virtual const CMkAudioParam& GetAudioParam() const { return m_AudioParam; }
    virtual const CMkVideoParam& GetVideoParam() const { return m_VideoParam; }
    void SetVideoParam(const CMkVideoParam& Param) { m_VideoParam = Param; }
    void SetAudioParam(const CMkAudioParam& Param) { m_AudioParam = Param; }
    const MkVector<MkCacheEsPacket>& GetCacheEsPacket() const { return m_CacheEsPacket; }
    void AddCacheEsPacket(const MkEsPacket& EsPacket);
    void SetStreamPath(const MkString& StreamPath) { m_StreamPath = StreamPath; }
    const MkString& GetStreamPath() const { return m_StreamPath; }
    void SetAppName(const MkString& AppName) { m_AppName = AppName; }
    void SetSession(const MkString& Session) { m_Session = Session; }
    const MkString& GetAppName() const { return m_AppName; }
    const MkMediaSourceType& GetSourceType() const { return m_SourceType; }
    float GetSpeed() const { return m_fSpeed; }
    BOOL IsPause() const { return m_bPause; }
    const MkString& GetSession() const { return m_Session; }
    const Uint64& GetRecvBytes() const { return m_RecvBytes; }
    const CMkTime& GetStartTime() const { return m_StartTime; }

    Uint32 AddConsumer(CMkMediaConsume* pConsume,CMkMediaConsumer* pConsumer);
    Uint32 DeleteConsumer(const MkMediaConsumeType& ConsumeType, const MkString& ConsumerSession, BOOL& bEmpty);
    Uint32 GetConsumer(const MkMediaConsumeType& ConsumeType, const MkString& ConsumerSession, CMkMediaConsumer** ppConsumer);
    const MkMap<MkMediaConsumeType, CMkMediaConsume*>& GetMapConsumer() const { return m_MapMediaConsume; }
protected:
    Uint32 OnReadEsPacket(const MkEsPacket& EsPacket);
private:
    void ClearCacheEsPacket();
    void ClearConsume();
public:
    CMkAudioParam               m_AudioParam;
    CMkVideoParam               m_VideoParam;
    Uint32                      m_Duration;
    Uint32                      m_FileSize;
    MkSourceResultCallback      m_ResultCb;
    MkEsPacketCallback          m_EsPacketCb;

    Uint8*                      m_pBuffer;  //this buffer is used to packet stream like ps rtmp 
    Uint32                      m_nMaxLen;
    Uint32                      m_nOffset;
protected:
private:
    static BOOL                 m_bCachePacket;
    MkString                    m_AppName;
    MkString                    m_Session;
    MkString                    m_StreamPath;
    Uint64                      m_RecvBytes;
    CMkTime                     m_StartTime;
    MkVector<MkCacheEsPacket>   m_CacheEsPacket;
    MkMediaSourceType           m_SourceType;
    std::atomic<float>          m_fSpeed;
    std::atomic<BOOL>           m_bPause;
    std::atomic<Uint32>         m_SeekPos;

    CMkRwLock                   m_ConsumerLock;
    MkMap<MkMediaConsumeType, CMkMediaConsume*> m_MapMediaConsume;
};

#endif